---
title: Composants
description: Une introduction aux composants Astro.
i18nReady: true
---
import ReadMore from '~/components/ReadMore.astro';

**Les composants Astro** sont les éléments de base de tout projet Astro. Il s'agit de composants de modèles en HTML uniquement, sans environnement d'exécution côté client et qui utilisent l'extension de fichier `.astro`.

:::note
Si vous connaissez le HTML, vous en savez déjà assez pour écrire votre premier composant Astro.

<ReadMore>Pour en savoir plus, consultez la [référence de la syntaxe d'Astro](/fr/reference/astro-syntax/).</ReadMore>
:::

Les composants Astro sont extrêmement flexibles. Un composant Astro peut être aussi petit qu'un extrait de HTML, comme une collection de balises `<meta>` communes qui facilitent le travail de référencement. Les composants peuvent être des éléments réutilisables de l'interface utilisateur, comme un en-tête ou une fiche de profil. Les composants Astro peuvent même contenir une mise en page entière ou, lorsqu'ils sont situés dans le dossier spécial `src/pages/`, être une page entière.

La chose la plus importante à savoir à propos des composants Astro est qu'ils **ne sont pas générés côté client**. Ils sont restitués en HTML soit au moment de la compilation, soit à la demande. Vous pouvez inclure du code JavaScript à l'intérieur du frontmatter de votre composant, et tout ce code sera retiré de la page finale envoyée aux navigateurs de vos utilisateurs. Le résultat est un site plus rapide, sans aucune empreinte JavaScript ajoutée par défaut.

Lorsque votre composant Astro nécessite une interactivité côté client, vous pouvez ajouter des [balises HTML standards de `<script>`](/fr/guides/client-side-scripts/) ou des [composants de framework UI](/fr/guides/framework-components/#hydratation-des-composants-interactifs) en tant qu'« îlots de client ».

Pour les composants qui doivent afficher du contenu personnalisé ou dynamique, vous pouvez différer leur rendu sur le serveur en ajoutant une [directive serveur](/fr/reference/directives-reference/#directives-serveur). Ces « îlots de serveur » restitueront leur contenu lorsqu'il sera disponible, sans retarder le chargement complet de la page.

## Structure du composant

Un composant Astro est composé de deux parties principales : le **script du composant** et le **modèle du composant**. Chaque partie accomplit un travail différent, mais ensemble, elles fournissent un cadre à la fois facile à utiliser et suffisamment expressif pour gérer tout ce que vous souhaitez créer.

```astro title="src/components/ComposantVide.astro"
---
// Script du composant (JavaScript)
---
<!-- Modèle du composant (HTML + Expressions JS) -->
```

### Le script du composant

Astro utilise des délimiteurs de code (`---`) pour identifier le script du composant dans votre composant Astro. Si vous avez déjà écrit du Markdown avant, vous pourriez être déjà familier avec un concept similaire appelé *frontmatter.* Astro est directement inspiré de cela.

Vous pouvez utiliser le script du composant pour écrire le code JavaScript nécessaire au rendu de votre modèle. Cela peut inclure :

- importer d'autres composants Astro
- importer des composants de framework, comme React
- importer des données, comme un fichier JSON
- récupérer du contenu à partir d'une API ou d'une base de données
- créer des variables que vous voulez référencer dans votre modèle

```astro title="src/components/MonComposant.astro"
---
import UnComposantAstro from '../components/UnComposantAstro.astro';
import UnComposantReact from '../components/UnComposantReact.jsx';
import desDonnees from '../data/pokemon.json';

// Accéder aux props de composants transmis, comme `<X title="Hello, World" />`
const { title } = Astro.props;

// Récupérer des données externes, même à partir d'une API ou d'une base de données privée
const data = await fetch('UNE_URL_SECRETE_API/utilisateurs').then(r => r.json());
---
<!-- Votre modèle ici ! -->
```

Le délimiteur de code est conçu pour garantir que le code JavaScript que vous écrivez à l'intérieur « ne puisse pas s'échapper ». Il ne sera pas visible dans le frontend de votre application et ne tombera pas entre les mains de votre utilisateur. Vous pouvez écrire du code JavaScript coûteux (en terme de performance) ou sensible (comme un appel à votre base de données privée) sans vous soucier qu'il se retrouve dans le navigateur l'utilisateur.

:::note
Le script du composant Astro utilise TypeScript, ce qui vous permet d'ajouter une syntaxe supplémentaire à JavaScript pour les outils d'édition et la vérification des erreurs.

<ReadMore>En savoir plus sur la [prise en charge intégrée de TypeScript](/fr/guides/typescript/) dans Astro.</ReadMore>
:::

### Le modèle du composant

Le modèle de composant se trouve sous le délimiteur de code et détermine la sortie HTML de votre composant.

Si vous écrivez du HTML brut ici, votre composant affichera ce HTML dans n'importe quelle page Astro où il est importé et utilisé.

Cependant, la [syntaxe du modèle de composant d'Astro](/fr/reference/astro-syntax/) prend également en charge les **expressions JavaScript**, les balises [`<style>`](/fr/guides/styling/#mettre-en-forme-avec-astro) et [`<script>`](/fr/guides/client-side-scripts/) d'Astro, les **composants importés** et les [**directives spéciales d'Astro**](/fr/reference/directives-reference/). Les données et valeurs définies dans le script du composant peuvent être utilisées dans le modèle de composant pour produire du HTML créé dynamiquement.

```astro title="src/components/MyFavoritePokemon.astro"
---
// Le script de votre composant ici !
import Banner from '../components/Banner.astro';
import Avatar from '../components/Avatar.astro';
import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
const myFavoritePokemon = [/* ... */];
const { title } = Astro.props;
---
<!-- Les commentaires HTML sont pris en charge ! -->
{/* La syntaxe des commentaires JavaScript est aussi valide ! */}

<Banner />
<h1>Hello, world!</h1>

<!-- Utiliser les props et autres variables du script du composant : -->
<p>{title}</p>

<!-- Retarder le rendu des composants et fournir un contenu de chargement de secours : -->
<Avatar server:defer>
  <svg slot="fallback" class="avatar-generique" transition:name="avatar">...</svg>
</Avatar>

<!-- Inclure d'autres composants de framework UI avec une directive `client:` pour l'hydrater : -->
<ReactPokemonComponent client:visible />

<!-- Mélanger du HTML avec des expressions JavaScript, similaire à la syntaxe JSX : -->
<ul>
  {myFavoritePokemon.map((data) => <li>{data.name}</li>)}
<ul>

<!-- Utiliser une directive de modèle pour créer des noms de classe à partir de plusieurs chaînes de caractères ou même d’objets ! -->
<p class:list={["ajouter", "dynamiquement", { desClasses: true }]} />
```

## Conception basée sur les composants

Les composants sont conçus pour être **réutilisables** et **composables**. Vous pouvez utiliser des composants à l'intérieur d'autres composants pour créer une interface utilisateur de plus en plus complexe. Par exemple, un composant `Button` pourrait être utilisé pour créer un composant `ButtonGroup` comme ceci :

```astro title="src/components/ButtonGroup.astro"
---
import Button from './Button.astro';
---
<div>
  <Button title="Bouton 1" />
  <Button title="Bouton 2" />
  <Button title="Bouton 3" />
</div>
```

## Props de composant

Un composant Astro peut définir et accepter des props (diminutif pour « propriétés »). Ces dernières deviennent alors disponibles dans le modèle du composant pour le rendu du HTML. Les props sont accessibles à l'aide de la variable globale `Astro.props` dans le frontmatter, ou script du composant.

Voici un exemple de composant qui reçoit une propriété nommée `greeting` et une autre nommée `name`. Notez que les props à recevoir sont déstructurées de l'objet global `Astro.props`.

```astro "Astro.props"
---
// src/components/GreetingHeadline.astro
// Utilisation : <GreetingHeadline greeting="Comment ça va" name="Partenaire" />
const { greeting, name } = Astro.props;
---
<h2>{greeting}, {name} !</h2>
```

Ce composant, lorsqu'il est importé et rendu dans d'autres composants, mises en page ou pages Astro, peut transmettre ces props sous forme d'attributs :

```astro /(\w+)=\S+/
---
// src/components/GreetingCard.astro
import GreetingHeadline from './GreetingHeadline.astro';
const name = 'Astro';
---
<h1>Carte de bienvenue</h1>
<GreetingHeadline greeting="Salut" name={name} />
<p>J'espère que vous passez une merveilleuse journée !</p>
```

Vous pouvez également définir le type de vos props avec TypeScript en créant une interface nommée `Props`. Astro sélectionnera automatiquement l'interface `Props` dans le frontmatter et donnera des avertissements/erreurs de type. Ces props peuvent également recevoir des valeurs par défaut lorsqu'elles sont déstructurées à partir d'`Astro.props`.

```astro ins={3-6}
---
// src/components/GreetingHeadline.astro
interface Props {
  name: string;
  greeting?: string;
}

const { greeting = "Salut", name } = Astro.props;
---
<h2>{greeting}, {name} !</h2>
```

Les props de composant peuvent recevoir des valeurs par défaut à utiliser lorsqu'aucune n'est fournie.

```astro ins="= \"Salut\"" ins="= \"Astronaute\""
---
// src/components/GreetingHeadline.astro
const { greeting = "Salut", name = "Astronaute" } = Astro.props;
---
<h2>{greeting}, {name} !</h2>
```

## Les slots

L'élément `<slot />` est une balise substituable par du contenu HTML externe, vous permettant d'injecter des éléments enfants depuis d'autres fichiers dans votre modèle de composant.

Par défaut, tous les éléments enfants passés à un composant seront restitués dans son `<slot />`.

:::note
Contrairement aux *props*, qui sont des attributs transmis à un composant Astro et accessibles dans l'ensemble de ce composant avec `Astro.props`, _les slots_ restituent les éléments HTML enfants là où ils sont placés.
:::

```astro "<slot />"
---
// src/components/Wrapper.astro
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props;
---
<div id="content-wrapper">
  <Header />
  <Logo />
  <h1>{title}</h1>
  <slot /> <!-- les élement enfants seront insérés ici -->
  <Footer />
</div>
```

```astro {6-7}
---
// src/pages/fred.astro
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Page de Fred">
  <h2>Tout ce qui est a savoir sur Fred</h2>
  <p>Voici quelques trucs à propos de Fred.</p>
</Wrapper>
```

Ce modèle est la base d'un [composant de mise en page Astro](/fr/basics/layouts/) : une page entière de contenu HTML peut être « enveloppée » avec des balises `<Layout></Layout>` et envoyée au composant pour être restituée à l'intérieur des éléments de page communs qui y sont définis.

<ReadMore>Consultez les [fonctions utilitaires `Astro.slots`](/fr/reference/astro-syntax/#astroslots) pour découvrir d'autres moyens d'accéder au contenu des slots et de le restituer.</ReadMore>

### Les slots nommés

Un composant Astro peut aussi avoir des slots nommés. Cela vous permet de transmettre uniquement les éléments HTML portant le nom du slot correspondant à l'emplacement d'un slot.

Les slots sont nommés à l'aide de l'attribut `name` :

```astro /<slot.*?/>/
---
// src/components/Wrapper.astro
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props;
---
<div id="content-wrapper">
<Header />
<!-- les enfants avec l'attribut `slot="after-header"` iront ici  -->
<slot name="after-header" />
<Logo />
<h1>{title}</h1>
<!-- les enfants sans `slot` ou avec l'attribut `slot="default"` iront ici -->
<slot />
<Footer />
<!-- les enfants avec l'attribut `slot="after-footer"` iront ici -->
<slot name="after-footer" />
</div>
```

Pour injecter du contenu HTML dans un slot particulier, utilisez l'attribut `slot` sur n'importe quel élément enfant pour spécifier le nom du slot. Tous les autres éléments enfants du composant seront injectés dans le `<slot />` par défaut (sans nom).

```astro /slot=".*?"/
---
// src/pages/fred.astro
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Page de Fred">
  <img src="https://ma.photo/fred.jpg" slot="after-header" />
  <h2>Tout ce qui est a savoir sur Fred</h2>
  <p>Voici quelques trucs à propos de Fred.</p>
  <p slot="after-footer">Copyright 2022</p>
</Wrapper>
```

:::tip
Utilisez un attribut `slot="mon-slot"` sur l'élément enfant que vous souhaitez transmettre à un emplacement réservé `<slot name="mon-slot" />` correspondant dans votre composant.
:::

Pour transmettre plusieurs éléments HTML dans l'emplacement réservé `<slot/>` d'un composant sans qu'ils soient enveloppés par une balise `<div>`, utilisez l'attribut `slot=""` sur le [composant `<Fragment/>` d'Astro](/fr/reference/astro-syntax/#fragments):

```astro title="src/components/CustomTable.astro" '<slot name="header" />' '<slot name="body" />'
---
// Crée un tableau personnalisé avec des slots nommés pour le contenu de l'en-tête et du corps
---
<table class="bg-white">
  <thead class="sticky top-0 bg-white"><slot name="header" /></thead>
  <tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="body" /></tbody>
</table>
```

Injectez plusieurs lignes et colonnes de contenu HTML en utilisant un attribut `slot=""` pour spécifier le contenu de l'en-tête (`"header"`) et du corps (`"body"`). Les éléments HTML individuels peuvent également être mis en forme :

```astro title="src/components/StockTable.astro" {5-7, 9-13} '<Fragment slot="header">' '<Fragment slot="body">' '</Fragment>'
---
import CustomTable from './CustomTable.astro';
---
<CustomTable>
  <Fragment slot="header"> <!-- passer l'en-tête du tableau -->
    <tr><th>Nom du produit</th><th>Unités en stock</th></tr>
  </Fragment>

  <Fragment slot="body"> <!-- passer le corps du tableau -->
    <tr><td>Tongs</td><td>64</td></tr>
    <tr><td>Bottes</td><td>32</td></tr>
    <tr><td>Baskets</td><td class="text-red-500">0</td></tr>
  </Fragment>
</CustomTable>
```

Notez que les slots nommés doivent être des enfants immédiats du composant. Il n'est pas possible de transmettre des slots nommés à travers des éléments imbriqués.

:::tip
Les slots nommés peuvent aussi être transmis aux [composants de framework UI](/fr/guides/framework-components/) !
:::

:::note
Il n'est pas possible de générer dynamiquement un nom de slot Astro en utilisant, par exemple, la méthode [`map`](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Si cette fonctionnalité est nécessaire dans les composants du framework UI, il est préférable de générer ces slots dynamiques dans le framework lui-même.
:::

### Contenu de repli pour les slots

Les slots peuvent également restituer du **contenu de repli**. Lorsqu'aucun enfant correspondant n'est transmis à un slot, un élément `<slot />` utilisera ses propres enfants comme contenu par défaut.

```astro {14}
---
// src/components/Wrapper.astro
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props;
---
<div id="content-wrapper">
  <Header />
  <Logo />
  <h1>{title}</h1>
  <slot>
    <p>Ceci est mon contenu de repli, s'il n'y a pas d'enfant passé au slot</p>
  </slot>
  <Footer />
</div>
```

Le contenu de repli ne sera affiché que lorsqu'aucun élément correspondant avec l'attribut `slot="name"` n'est transmis à un slot nommé.

Astro transmet un slot vide lorsqu'un élément slot existe, mais qu'il n'y a pas de contenu à transmettre. Le contenu de repli ne peut pas être utilisé par défaut lorsqu'un slot vide est transmis. Le contenu de repli n'est affiché que quand aucun élément slot ne peut être trouvé.

### Transférer des slots

Les slots peuvent être transférés à d'autres composants. Par exemple, lorsque l'on crée des mises en page imbriquées :

```astro title="src/layouts/BaseLayout.astro" {9,12}
---
---
<html lang="fr">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
    <slot name="head" />
	</head>
	<body>
		<slot />
	</body>
</html>
```

```astro {6,7}
// src/layouts/HomeLayout.astro
---
import BaseLayout from './BaseLayout.astro';
---
<BaseLayout>
  <slot name="head" slot="head" />
  <slot />
</BaseLayout>
```

:::note
Les slots nommés peuvent être transférés vers un autre composant en utilisant les attributs `name` et `slot` sur une balise `<slot />`.
:::

Maintenant, les slots par défaut et `head` passés à `HomeLayout` seront transférés au parent `BaseLayout`.

```astro
// src/pages/index.astro
---
import HomeLayout from '../layouts/HomeLayout.astro';
---
<HomeLayout>
	<title slot="head">Astro</title>
	<h1>Astro</h1>
</HomeLayout>
```

## Composants HTML

Astro prend en charge l'importation et l'utilisation de fichiers `.html` en tant que composants ou le placement de ces fichiers dans le sous-répertoire `src/pages` en tant que pages. Vous souhaiterez peut-être utiliser des composants HTML si vous réutilisez le code d'un site existant créé sans framework ou si vous souhaitez vous assurer que votre composant ne possède aucune fonctionnalité dynamique.

Les composants HTML ne doivent contenir que du code HTML valide et ne disposent donc pas des fonctionnalités clés des composants Astro :

- Ils ne prennent pas en charge le frontmatter, les importations côté serveur ou les expressions dynamiques.
- Toutes les balises `<script>` sont laissées non regroupées, traitées comme si elles avaient une [directive `is:inline`](/fr/reference/directives-reference/#isinline).
- Ils ne peuvent [référencer que les ressources qui se trouvent dans le dossier `public/`](/fr/basics/project-structure/#public).

:::note
Un [élément `<slot />`](#les-slots) à l'intérieur d'un composant HTML fonctionnera comme il le ferait dans un composant Astro. Pour utiliser l'élément [slot des composants web](https://developer.mozilla.org/fr/docs/Web/HTML/Element/slot) à la place, ajoutez `is:inline` à votre élément `<slot>`.
:::

## Étapes suivantes

<ReadMore>En apprendre plus sur l'utilisation de [composants de framework UI](/fr/guides/framework-components/) dans votre projet Astro.</ReadMore>
